
package slave;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

/**
 * 
 * @author erond
 * @class Classe che implementa il protocollo di comunicazione con il MasterJobServerThread
 */
public class SlaveJobClientThread extends Thread {

	private Socket slaveClientSocket = null;
	private SlaveComunicator sc = null;

	/**
	 * Costruttore.
	 * @param sc Riferimento allo SlaveComunicator
	 */
	public SlaveJobClientThread(SlaveComunicator sc) {
		this.sc=sc;
	}	

	//metodo per lanciare il thread
	public void run() {

		System.out.println("SlaveJobClientThread avviato...");	

		try {
			slaveClientSocket=new Socket(sc.masterJobServerIP,sc.getMasterJobServerPort());
			slaveClientSocket.setReuseAddress(true);
			System.out.println("SlaveJobClientThread: creata la Socket di comunicazione col masterServer: "+slaveClientSocket);
		} catch (IOException e) {
			e.printStackTrace();
		}	
		DataInputStream inSock = null;
		DataOutputStream outSock = null;

		try {
			// creazione stream di input e out da socket
			inSock = new DataInputStream(slaveClientSocket.getInputStream());
			outSock = new DataOutputStream(slaveClientSocket.getOutputStream());
		}
		catch (IOException ioe) {
			System.out
			.println("SlaveJobClientThread: Problemi nella creazione degli stream di input/output "
					+ "su socket: ");
			ioe.printStackTrace();
			// il server continua l'esecuzione riprendendo dall'inizio del ciclo
			return;
		}

		boolean ciclo=true;
		while(ciclo) {

			try {

				/**
				 * 1) attendo di ricevere INQUIRYREADY dal MASTER
				 */

				System.out.println(Thread.currentThread().getName()+": Attendo di ricevere INQUIRYREADY dal MASTER...");
				String signal=null;

				try {
					while(inSock.available()>=0) {

						signal=inSock.readUTF();
						if(signal.equalsIgnoreCase("INQUIRYREADY")) {
							System.err.println(Thread.currentThread().getName()+": Ricevuto "+signal+" ..avvio la procedura!");
							/**
							 * se ricevo questa stringa vuol dire che il vicino MASTER ha inviato al mio ftp server
							 * il file contenente i mac address relativi all'inquiry BT appena effettuato.
							 * CONTROLLO DI SICUREZZA: invio al vicino la stringa INQUIRYREADYRECEIVED
							 */
							outSock.writeUTF("INQUIRYREADYRECEIVED");
							break;
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
					System.exit(1);
				}


				try {
					outSock.flush();
				} catch (IOException ioe) {
					System.err.println(Thread.currentThread().getName()+": Eccezione nella flush");
					ioe.printStackTrace();
				}

				/**
				 * 2) calcolo LAMBDA e aggiorno il file gateway.xml, dopodichè lo pubblico sul multicast
				 *    ed invio al master il segnale OKDOWNLOADXML. Nel caso di problemi invio ERROR.
				 */

				//scateno l'evento di calcolo LAMBDA verso lo SlaveStreamProvider
				SlaveComunicator.InquiryReadyEvent ire = sc.new InquiryReadyEvent(sc);


				//attendo dallo SlaveStreamProvider un evento che mi confermi che l'operazione è terminata con successo
				//mi sospendo in attesa che il calcolo del LAMBDA e relativo aggiornamento dell'xml venga completato
				synchronized (this) {
					try {
						sc.fireInquiryReadyEvent(ire);
						sc.wait = true; 
						this.wait();
					} catch (InterruptedException e2) {
						e2.printStackTrace();
					}
				}

				//	System.err.println("SlaveJobClientThread: sbloccata la wait! Ora invio OKDOWNLOADXML e attendo GRAZIE..");

				String tmp="OKDOWNLOADXML";
				boolean GRAZIE=false;

				try {
					while(!GRAZIE) {
						outSock.writeUTF(tmp);
						while(inSock.available()>=0) {
							tmp=inSock.readUTF();
							if (tmp.contains("GRAZIE")) {
								System.out.println("SlaveJobClientThread: Ricevo: "+tmp+" ..posso chiudere!");
								GRAZIE=true;
								break;
							}
						}
					}//fine while(!GRAZIE)

				}catch (IOException ioe) {
					ioe.printStackTrace();
					System.exit(1);
				}

				try {
					outSock.flush();
				} catch (IOException ioe) {
					System.err.println(Thread.currentThread().getName()+": Eccezione nella flush");
					ioe.printStackTrace();
				}

				/**
				 * 3) Infine mi metto in attesa di ricevere la lista di JOB da eseguire (job.xml)
				 */ 	

				//	System.out.println(Thread.currentThread().getName()+": Attendo di ricevere JOBREADY dal MASTER...");

				try {
					while(inSock.available()>=0) {
						signal=inSock.readUTF();
						if(signal.equalsIgnoreCase("JOBREADY")) {
							//		System.err.println(Thread.currentThread().getName()+": Ricevuto "+signal+" ..avvio la procedura!");
							/**
							 * se ricevo questa stringa vuol dire che il vicino MASTER mi ha inviato al server ftp
							 * il file job.xml contenente i job da avviare.
							 * CONTROLLO DI SICUREZZA: invio al vicino la stringa JOBREADYRECEIVED
							 */
							outSock.writeUTF("JOBREADYRECEIVED");
							break;
						}
					}
				} catch (IOException e) {
					System.out.println("ECCEZIONE SULLA SOCKET "+slaveClientSocket.toString());
					e.printStackTrace();
					System.exit(1);
				}


				try {
					outSock.flush();
				} catch (IOException ioe) {
					System.err.println(Thread.currentThread().getName()+": Eccezione nella flush");
					ioe.printStackTrace();
				}

				System.out.println(Thread.currentThread().getName()+": Ricevuto job.xml dal MASTER");

				/**
				 * a questo punto lo slave dovrebbe poter avviare i servizi con i client.
				 * La comunicazione MASTER-SLAVE può ritornare all'inizio del protocollo.
				 * Devo poter inviare a SlaveMaster un evento di comando
				 */

				System.out.println("SlaveJobClientThread: scateno un jobReadyEvent..");
				SlaveComunicator.JobReadyEvent jbe = sc.new JobReadyEvent(sc, sc.sm);
				sc.fireJobReadyEvent(jbe);



			} catch (Exception e) {
				/**
				 * Chiusura socket ed I/O stream
				 */
				System.err.println("SlaveJobClientThread: Errore,chiudo...\n");
				e.printStackTrace();
				try {
					inSock.close();
					outSock.close();
					slaveClientSocket.close();
					System.exit(10);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				System.out.println("SlaveJobClientThread: Chiudo i canali I/O e la socket");
			}

		}//fine while(true)

	}//fine run()

}//fine SlaveJobClientThread
